﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Windows;
using System.Windows.Input;
using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Command;
using GalaSoft.MvvmLight.Messaging;
using Microsoft.Win32;
using WhiteRepositoryExplorer.Messeges;
using WhiteRepositoryExplorer.Model;
using WhiteRepositoryExplorer.Repository;
using WpfMessageBox = Xceed.Wpf.Toolkit.MessageBox;

namespace WhiteRepositoryExplorer.ViewModel
{
    /// <summary>
    /// This class contains properties that the main View can data bind to.
    /// <para>
    /// Use the <strong>mvvminpc</strong> snippet to add bindable properties to this ViewModel.
    /// </para>
    /// <para>
    /// You can also use Blend to data bind with the tool's support.
    /// </para>
    /// <para>
    /// See http://www.galasoft.ch/mvvm/getstarted
    /// </para>
    /// </summary>
    public class MainViewModel : ViewModelBase
    {
        #region ctor
        /// <summary>
        /// Initializes a new instance of the MainViewModel class.
        /// </summary>
        public MainViewModel()
        {
            _recentFiles.LoadXml();
        }

        #endregion ctor

        #region private members

        private readonly XmlRepositoryReader _repositoryReader = new XmlRepositoryReader();
        private string _pathToXml;
        private WhiteControl _selectedControl;
        private int _selectedIndex;
        private string _filter;
        private readonly RecentFiles _recentFiles = new RecentFiles();
        private bool _isFindDuplicatesChecked;

        #endregion private members

        #region private commands

        private ICommand _importXmlCommand;
        private ICommand _refreshCommand;
        private ICommand _findDuplicatesCommand;
        private ICommand _clearFilterCommand;
        private ICommand _exitCommand;
        private ICommand _aboutCommand;
        private ICommand _focusFilterCommand;
        private ICommand _openXmlFolderCommand;
        private ICommand _importRecentItemCommand;

        #endregion private commands

        #region public commands

        public ICommand ImportXmlCommand
        {
            get { return _importXmlCommand ?? (_importXmlCommand = new RelayCommand(ImportXmlCommandExecuted)); }
        }

        public ICommand RefreshCommand
        {
            get { return _refreshCommand ?? (_refreshCommand = new RelayCommand(RefreshCommandExecuted, RefreshCommandCanExecute)); }
        }

        public ICommand FindDuplicatesCommand
        {
            get { return _findDuplicatesCommand ?? (_findDuplicatesCommand = new RelayCommand(FindDuplicatesCommandExecuted, FindDuplicatesCommandCanExecute)); }
        }

        public ICommand ClearFilterCommand
        {
            get { return _clearFilterCommand ?? (_clearFilterCommand = new RelayCommand(ClearFilterCommandExecuted, ClearFilterCommandCanExecute)); }
        }

        public ICommand ExitCommand
        {
            get { return _exitCommand ?? (_exitCommand = new RelayCommand(ExitCommandExecuted)); }
        }

        public ICommand AboutCommand
        {
            get { return _aboutCommand ?? (_aboutCommand = new RelayCommand(AboutCommandExecuted)); }
        }

        public ICommand FocusFilterCommand
        {
            get { return _focusFilterCommand ?? (_focusFilterCommand = new RelayCommand(FocusFilterCommandExecuted, FocusFilterCommandCanExecute)); }
        }

        public ICommand OpenXmlFolderCommand
        {
            get { return _openXmlFolderCommand ?? (_openXmlFolderCommand = new RelayCommand(OpenXmlFolderCommandExecuted, OpenXmlFolderCommandCanExecute)); }
        }

        public ICommand ImportRecentItemCommand
        {
            get { return _importRecentItemCommand ?? (_importRecentItemCommand = new RelayCommand<object>(ImportRecentItemCommandExecuted)); }
        }



        #endregion public commands

        #region command handlers
        
        private void ImportXmlCommandExecuted()
        {
            var openDlg = new OpenFileDialog
            {
                Title = "Import XML",
                DefaultExt = ".xml",
                Filter = "XML Repository (.xml)|*.xml",
                Multiselect = false
            };

            bool? result = openDlg.ShowDialog();
            if (result != true) return;


            try
            {
                _repositoryReader.ReadRepository(openDlg.FileName);

            }
            catch (InvalidDataException)
            {
                WpfMessageBox.Show("Repository XML has wrong format", "Wrong data", MessageBoxButton.OK, MessageBoxImage.Error);
                return;
            }

            _pathToXml = openDlg.FileName;
            _recentFiles.Add(openDlg.FileName);

            RaisePropertyChanged("Controls");
            RaisePropertyChanged("PathToXml");
            RaisePropertyChanged("RecentFiles");
            Filter = string.Empty;

            SelectedIndex = 0;

        }

        private bool RefreshCommandCanExecute()
        {
            return _pathToXml != null;
        }

        private void RefreshCommandExecuted()
        {
            _repositoryReader.ReadRepository(_pathToXml);
            RaisePropertyChanged("Controls");
            SelectedIndex = 0;
            Filter = string.Empty;
        }

        private bool FindDuplicatesCommandCanExecute()
        {
            return _pathToXml != null;
        }

        private void FindDuplicatesCommandExecuted()
        {
            
        }

        private bool ClearFilterCommandCanExecute()
        {
            return _pathToXml != null;
        }

        private void ClearFilterCommandExecuted()
        {
            Filter = string.Empty;
            
        }

        private void ExitCommandExecuted()
        {
            MessageBoxResult result = WpfMessageBox.Show("Do you want to exit?", "Exiting", MessageBoxButton.YesNo, MessageBoxImage.Question);
            if (result == MessageBoxResult.Yes)
            {
                Application.Current.Shutdown();    
            }
            
        }

        private void AboutCommandExecuted()
        {
            Messenger.Default.Send(new ShowAboutWindowMessage());
        }

        private bool FocusFilterCommandCanExecute()
        {
            return _pathToXml != null;
        }

        private void FocusFilterCommandExecuted()
        {
            Messenger.Default.Send(new FocusFilterMessage());
        }

        private bool OpenXmlFolderCommandCanExecute()
        {
            return _pathToXml != null;
        }

        private void OpenXmlFolderCommandExecuted()
        {
            Process.Start("explorer.exe", "/select," + PathToXml);
        }

        private void ImportRecentItemCommandExecuted(object parameter)
        {
            string path = parameter.ToString();
            try
            {
                path = parameter.ToString();
                _repositoryReader.ReadRepository(path);
                _recentFiles.Add(path);
                _pathToXml = path;
            }
            catch (FileNotFoundException)
            {
                MessageBoxResult result = WpfMessageBox.Show(string.Format("XML repository file not found.\nDo you want to remove the reference from the recent files list?"),
                    "File not found", MessageBoxButton.YesNo, MessageBoxImage.Question);
                if (result == MessageBoxResult.Yes)
                {
                    _recentFiles.Remove(path);
                    RaisePropertyChanged("RecentFiles");
                }
                return;
            }

            RaisePropertyChanged("Controls");
            RaisePropertyChanged("PathToXml");
            RaisePropertyChanged("RecentFiles");
            Filter = string.Empty;

            SelectedIndex = 0;
        }

        #endregion command handlers

        #region public properties for binding

        public List<WhiteControl> Controls
        {
            get
            {
                if (!string.IsNullOrWhiteSpace(Filter))
                {
                    return _repositoryReader.Filter(Filter);
                }
                if (IsFindDuplicatesChecked)
                {
                    return _repositoryReader.Duplicates();
                }
                return _repositoryReader.Controls;
                
            }
        }

        public WhiteControl SelectedControl
        {
            get
            {
                return _selectedControl;
            }
            set
            {
                if (value != _selectedControl)
                {
                    _selectedControl = value;
                    RaisePropertyChanged("SelectedControl");
                    RaisePropertyChanged("PathToXml");
                }
            }
        }

        public int SelectedIndex
        {
            get { return _selectedIndex; }    
            set
            {
                if (value != _selectedIndex)
                {
                    _selectedIndex = value;
                    RaisePropertyChanged("SelectedIndex");
                    RaisePropertyChanged("PathToXml");
                    RaisePropertyChanged("SelectedControl");
                }
            }
        }

        public string Filter
        {
            get { return _filter; }
            set
            {
                if (!value.Equals(_filter))
                {
                    _filter = value;
                    RaisePropertyChanged("Filter");
                    RaisePropertyChanged("Controls");
                    SelectedIndex = 0;
                }
            }
        }

        public string PathToXml
        {
            get { return _pathToXml; }
        }

        public List<RecentFile> RecentFiles
        {
            get { return _recentFiles.Files; }
        }

        public bool IsFindDuplicatesChecked
        {
            get { return _isFindDuplicatesChecked; }
            set
            {
                if (value != _isFindDuplicatesChecked)
                {
                    _isFindDuplicatesChecked = value;
                    RaisePropertyChanged("IsFindDuplicatesChecked");
                    Filter = string.Empty;
                    RaisePropertyChanged("Controls");
                }
            }
        }

        #endregion public properties for binding

        //public override void Cleanup()
        //{
        //    // Clean up if needed
            

        //    base.Cleanup();
        //}
    }
}